package com.iptv.live.service.impl;

import com.iptv.common.exception.ServiceException;
import com.iptv.common.utils.EncryptionUtil;
import com.iptv.common.utils.StringUtils;
import com.iptv.live.domain.LivePreviewTable;
import com.iptv.live.domain.LivePreviewType;
import com.iptv.live.domain.dto.*;
import com.iptv.live.domain.qo.LivePreviewTableQO;
import com.iptv.live.domain.vo.LiveListTypeVO;
import com.iptv.live.domain.vo.LiveListVo;
import com.iptv.live.mapper.LivePreviewTableMapper;
import com.iptv.live.mapper.LivePreviewTypeMapper;
import com.iptv.live.mapper.LiveTypeTableMapper;
import com.iptv.live.service.ILivePreviewTableService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 直播频道Service业务层处理
 * 
 * @author Cinzia
 * @date 2025-01-03
 */
@Service
public class LivePreviewTableServiceImpl implements ILivePreviewTableService
{
    @Autowired
    private LivePreviewTableMapper livePreviewTableMapper;

    @Resource
    private LivePreviewTypeMapper livePreviewTypeMapper;

    @Resource
    private LiveTypeTableMapper liveTypeTableMapper;

    private static String password = "TP25076786123456";
    /**
     * 查询直播频道
     * 
     * @param id 直播频道主键
     * @return 直播频道
     */
    @Override
    public LivePreviewTable selectLivePreviewTableById(Long id)
    {
        return livePreviewTableMapper.selectLivePreviewTableById(id);
    }

    /**
     * 查询直播频道列表
     * 
     * @param livePreviewTableQO 直播频道
     * @return 直播频道
     */
    @Override
    public List<LivePreviewTable> selectLivePreviewTableList(LivePreviewTableQO livePreviewTableQO)
    {

        return livePreviewTableMapper.selectLivePreviewTableList(livePreviewTableQO.getKeyword(),livePreviewTableQO.getTypeId());
    }

    /**
     * 新增直播频道
     *
     * @param livePreviewTableAddDTO 直播频道
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public int insertLivePreviewTable(LivePreviewTableAddDTO livePreviewTableAddDTO) {
        int flag = 0;

        if (StringUtils.isNull(livePreviewTableAddDTO.getUrlId()) || StringUtils.isEmpty(livePreviewTableAddDTO.getName())) {
            throw new ServiceException("直播频道序号或直播名称不能为空");
        }

        LivePreviewTable livePreviewTable = new LivePreviewTable();
        livePreviewTable.setUrlId(livePreviewTableAddDTO.getUrlId());
        livePreviewTable.setName(livePreviewTableAddDTO.getName());
        livePreviewTable.setImage(livePreviewTableAddDTO.getImage());
        livePreviewTable.setLiveStream(livePreviewTableAddDTO.getLiveStream());

        List<LiveStreamDTO> highLiveStreamList = livePreviewTableAddDTO.getHighLiveStreamList();
        List<LiveStreamDTO> lowLiveStreamList = livePreviewTableAddDTO.getLowLiveStreamList();

        // 用来存储加密后的 URL 和密码
        List<String> encryptedHighUrls = new ArrayList<>();
        List<String> encryptedHighPasswords = new ArrayList<>();

        // 给高画质流加编号
        for (int i = 0; i < highLiveStreamList.size(); i++) {
            LiveStreamDTO highStream = highLiveStreamList.get(i);
            try {
                String encryptedUrl = EncryptionUtil.aesEncrypt("hd" + (i + 1) + ":" + highStream.getUrl(), password);
                String encryptedHdPassword = EncryptionUtil.aesEncrypt("hd" + (i + 1) + ":" + highStream.getPassword(), password);
                encryptedHighUrls.add(encryptedUrl);
                encryptedHighPasswords.add(encryptedHdPassword);
            } catch (Exception e) {
                throw new ServiceException("加密高画质流失败");
            }
        }

        List<String> encryptedLowUrls = new ArrayList<>();
        List<String> encryptedLowPasswords = new ArrayList<>();

        // 给低画质流加编号
        for (int i = 0; i < lowLiveStreamList.size(); i++) {
            LiveStreamDTO lowStream = lowLiveStreamList.get(i);
            try {
                String encryptedUrl = EncryptionUtil.aesEncrypt("sd" + (i + 1) + ":" + lowStream.getUrl(), password);
                String encryptedSdPassword = EncryptionUtil.aesEncrypt("sd" + (i + 1) + ":" + lowStream.getPassword(), password);
                encryptedLowUrls.add(encryptedUrl);
                encryptedLowPasswords.add(encryptedSdPassword);
            } catch (Exception e) {
                throw new ServiceException("加密低画质流失败");
            }
        }

        // 合并加密后的 URL 和密码
        String combinedEncryptedUrls = String.join(",", encryptedHighUrls) + "," + String.join(",", encryptedLowUrls);
        String combinedEncryptedPasswords = String.join(",", encryptedHighPasswords) + "," + String.join(",", encryptedLowPasswords);

        livePreviewTable.setUrl(combinedEncryptedUrls);
        livePreviewTable.setPassword(combinedEncryptedPasswords);

        int result = livePreviewTableMapper.insertLivePreviewTable(livePreviewTable);

        if (result > 0) {
            String typeIds = livePreviewTableAddDTO.getTypeId().stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            LivePreviewType livePreviewType = new LivePreviewType();
            livePreviewType.setLiveId(livePreviewTable.getId());
            livePreviewType.setLiveTypeId(typeIds);
            flag = livePreviewTypeMapper.insertLivePreviewType(livePreviewType);
        }

        return flag;
    }

    /**
     * 修改直播频道
     * 
     * @param livePreviewTableEditDTO 直播频道
     * @return 结果
     */
    @Override
    public int updateLivePreviewTable(LivePreviewTableEditDTO livePreviewTableEditDTO)
    {
        int flag = 0;

        if (StringUtils.isNull(livePreviewTableEditDTO.getUrlId()) || StringUtils.isEmpty(livePreviewTableEditDTO.getName())) {
            throw new ServiceException("直播频道序号或直播名称不能为空");
        }

        // 先更新序号，直播频道名称，图片，直播类型
        LivePreviewTable livePreviewTable = new LivePreviewTable();
        BeanUtils.copyProperties(livePreviewTableEditDTO,livePreviewTable);
        List<LiveStreamDTO> highLiveStreamList = livePreviewTableEditDTO.getHighLiveStreamList();
        List<LiveStreamDTO> lowLiveStreamList = livePreviewTableEditDTO.getLowLiveStreamList();

        // 用来存储加密后的 URL 和密码
        List<String> encryptedHighUrls = new ArrayList<>();
        List<String> encryptedHighPasswords = new ArrayList<>();

        // 给高画质流加编号
        for (int i = 0; i < highLiveStreamList.size(); i++) {
            LiveStreamDTO highStream = highLiveStreamList.get(i);
            try {
                String encryptedUrl = EncryptionUtil.aesEncrypt("hd" + (i + 1) + ":" + highStream.getUrl(), password);
                String encryptedHdPassword = EncryptionUtil.aesEncrypt("hd" + (i + 1) + ":" + highStream.getPassword(), password);
                encryptedHighUrls.add(encryptedUrl);
                encryptedHighPasswords.add(encryptedHdPassword);
            } catch (Exception e) {
                throw new ServiceException("加密高画质流失败");
            }
        }

        List<String> encryptedLowUrls = new ArrayList<>();
        List<String> encryptedLowPasswords = new ArrayList<>();

        // 给低画质流加编号
        for (int i = 0; i < lowLiveStreamList.size(); i++) {
            LiveStreamDTO lowStream = lowLiveStreamList.get(i);
            try {
                String encryptedUrl = EncryptionUtil.aesEncrypt("sd" + (i + 1) + ":" + lowStream.getUrl(), password);
                String encryptedSdPassword = EncryptionUtil.aesEncrypt("sd" + (i + 1) + ":" + lowStream.getPassword(), password);
                encryptedLowUrls.add(encryptedUrl);
                encryptedLowPasswords.add(encryptedSdPassword);
            } catch (Exception e) {
                throw new ServiceException("加密低画质流失败");
            }
        }

        // 合并加密后的 URL 和密码
        String combinedEncryptedUrls = String.join(",", encryptedHighUrls) + "," + String.join(",", encryptedLowUrls);
        String combinedEncryptedPasswords = String.join(",", encryptedHighPasswords) + "," + String.join(",", encryptedLowPasswords);

        livePreviewTable.setUrl(combinedEncryptedUrls);
        livePreviewTable.setPassword(combinedEncryptedPasswords);

        // 更新直播频道信息
        int result = livePreviewTableMapper.updateLivePreviewTable(livePreviewTable);
        if (result > 0) {
            // 删除现有的分类信息
            livePreviewTypeMapper.deleteLivePreviewTypeByLiveId(livePreviewTableEditDTO.getId());

            // 插入新的分类信息
            String typeIds = livePreviewTableEditDTO.getTypeId().stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            LivePreviewType livePreviewType = new LivePreviewType();
            livePreviewType.setLiveId(livePreviewTable.getId());
            livePreviewType.setLiveTypeId(typeIds);
            flag = livePreviewTypeMapper.insertLivePreviewType(livePreviewType);
        }


        return flag;
    }

    /**
     * 批量删除直播频道
     * 
     * @param ids 需要删除的直播频道主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public int deleteLivePreviewTableByIds(Long[] ids)
    {
        // 删除所有频道所绑定的分类
        int flag = 0;
        // 删除该频道所绑定的分类
        int result = livePreviewTypeMapper.deleteLivePreviewTypeByLiveIds(ids);
        if (result > 0) {
            flag = livePreviewTableMapper.deleteLivePreviewTableByIds(ids);
        }
        return flag;
    }

    /**
     * 删除直播频道信息
     * 
     * @param id 直播频道主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public int deleteLivePreviewTableById(Long id)
    {
        int flag = 0;
        // 删除该频道所绑定的分类
        int result = livePreviewTypeMapper.deleteLivePreviewTypeByLiveId(id);
        if (result > 0) {
            flag = livePreviewTableMapper.deleteLivePreviewTableById(id);
        }
        return flag;
    }

    @Override
    public List<LiveListTypeVO> getLiveType(Long id) {
        // 根据频道id获取分类id
        String liveTypeId = livePreviewTypeMapper.getLiveTypeId(id);

        // 判断liveTypeId是否为空或者为""，避免空指针异常
        if (liveTypeId == null || liveTypeId.isEmpty()) {
            return new ArrayList<>();  // 如果没有分类ID，返回空列表
        }

        // 将分类ID按逗号分割成数组
        String[] split = liveTypeId.split(",");

        List<LiveListTypeVO> liveTypes = new ArrayList<>();

        // 遍历每个分类 ID，进行查询
        for (String typeId : split) {
            // 查询每个分类的名称
            LiveListTypeVO liveType = liveTypeTableMapper.selectLiveTypeNameTableByTypeId(Long.parseLong(typeId));

            // 如果查询到的分类名称不为空，则添加到结果列表中
            if (liveType.getTypeName() != null) {
                liveTypes.add(liveType);
            }
        }

        return liveTypes;
    }

    @Override
    public List<LiveListVo> getLiveList() {

        // 获取所有直播数据
        List<LiveListDTO> livePreviewList = livePreviewTableMapper.getLiveList();

        // 用于按类型分组
        Map<String, List<LiveListDTO>> groupedData = new HashMap<>();

        // 用于存储每个类型对应的颜色
        Map<String, String> typeColorMap = new HashMap<>();

        for (LiveListDTO livePreview : livePreviewList) {
            String typeNames = livePreview.getTypeName();
            String color = livePreview.getColor();

            // 如果 typeNames 非空，则继续处理
            if (typeNames != null && !typeNames.isEmpty()) {
                String[] typeNameArray = typeNames.split(",");
                for (String typeName : typeNameArray) {
                    typeName = typeName.trim();

                    // 根据每个分类进行分组
                    groupedData.putIfAbsent(typeName, new ArrayList<>());
                    groupedData.get(typeName).add(livePreview);

                    // 为每个类型存储颜色，假设每个分类的颜色是相同的
                    typeColorMap.putIfAbsent(typeName, color);
                }
            }
        }

        // 用于存储结果
        List<LiveListVo> resultList = new ArrayList<>();

        // 将分组后的数据封装成 LiveListVo 并添加颜色
        for (Map.Entry<String, List<LiveListDTO>> entry : groupedData.entrySet()) {
            LiveListVo liveListVo = new LiveListVo();
            liveListVo.setTypeName(entry.getKey());  // 设置分类名称
            liveListVo.setLiveList(entry.getValue()); // 设置该分类下的直播数据

            // 获取并设置颜色
            String color = typeColorMap.get(entry.getKey());
            liveListVo.setColor(color);  // 设置分类颜色

            resultList.add(liveListVo);
        }

        return resultList;
    }

    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public int importLive(String type, List<LiveExportDTO> liveExportDTOList) {
        if (liveExportDTOList == null || liveExportDTOList.isEmpty()) {
            throw new ServiceException("导入列表为空");
        }

        if (Objects.equals(type, "cover")) {
            // 1. 收集所有分类 ID
            Set<Long> allTypeIds = new HashSet<>();
            for (LiveExportDTO dto : liveExportDTOList) {
                List<Long> typeIds = Arrays.stream(dto.getCategoryIds().split(","))
                        .map(Long::parseLong)
                        .collect(Collectors.toList());
                allTypeIds.addAll(typeIds);
            }

            // 2. 删除所有相关旧数据
            try {
                for (Long typeId : allTypeIds) {
                    List<Long> liveIds = livePreviewTypeMapper.selectLiveIdsList(typeId);
                    for (Long liveId : liveIds) {
                        livePreviewTableMapper.deleteLivePreviewTableById(liveId);
                    }
                    livePreviewTypeMapper.deleteLivePreviewTypeByLiveTypeId(typeId);
                }
            } catch (Exception e) {
                throw new ServiceException("删除旧数据失败");
            }
        }

        // 3. 处理每个 DTO（插入新数据）
        for (LiveExportDTO liveExportDTO : liveExportDTOList) {
            // 解析 URL、密码加密、插入数据等逻辑（保持原逻辑）
            processAndInsertLiveExportDTO(liveExportDTO, type);
        }

        return 0;
    }

    // 提取公共处理逻辑为独立方法
    private void processAndInsertLiveExportDTO(LiveExportDTO dto, String type) {
        HashSet<Long> typeIdsSet = new HashSet<>();
        List<Long> collect = Arrays.stream(dto.getCategoryIds().split(","))
                .map(Long::parseLong)
                .collect(Collectors.toList());
        typeIdsSet.addAll(collect);

        // 解析 URL 和密码
        String[] urlsAndPasswords = dto.getUrl().split(",");
        List<String> encryptedUrls = new ArrayList<>();
        List<String> encryptedPasswords = new ArrayList<>();

        // 直接处理URL和密码，分别加密
        for (int i = 0; i < urlsAndPasswords.length; i++) {
            String urlPasswordPair = urlsAndPasswords[i];
            Pattern pattern = Pattern.compile("(hd\\d|sd\\d):([^,]+)");
            Matcher matcher = pattern.matcher(urlPasswordPair);
            if (matcher.find()) {
                String streamTypeAndNumber = matcher.group(1);  // hd1, hd2, sd1
                String url = matcher.group(2);  // 对应的 URL
                try {
                    // 根据流类型进行加密
                    String encryptedUrl = EncryptionUtil.aesEncrypt(streamTypeAndNumber + ":" + url, password);
                    encryptedUrls.add(encryptedUrl);

                    // 从 password 字段中获取对应密码
                    String passwordPair = dto.getPassword();
                    Pattern passwordPattern = Pattern.compile(streamTypeAndNumber + ":(\\S+)");
                    Matcher passwordMatcher = passwordPattern.matcher(passwordPair);
                    if (passwordMatcher.find()) {
                        String pass = passwordMatcher.group(1);  // 对应的密码
                        if (pass.isEmpty()) {
                            // 如果密码为空，则将密码设置为 " "（空格）然后加密
                            pass = ",";
                        }
                        // 加密密码
                        String encryptedPassword = EncryptionUtil.aesEncrypt(streamTypeAndNumber + ":" + pass, password);
                        encryptedPasswords.add(encryptedPassword);
                    } else {
                        // 如果没有找到密码，抛出异常
                        throw new ServiceException("密码匹配失败，无法加密");
                    }
                } catch (Exception e) {
                    throw new ServiceException("加密 URL 或密码失败");
                }
            }
        }

        // 合并加密后的 URL 和密码，并加上逗号
        String combinedEncryptedUrls = String.join(",", encryptedUrls);
        String combinedEncryptedPasswords = String.join(",", encryptedPasswords);

        // 在合并密码时，确保尾部逗号的正确性
        if (!combinedEncryptedUrls.isEmpty() && !combinedEncryptedPasswords.isEmpty()) {
            // 加入一个逗号连接
            combinedEncryptedUrls += "," + combinedEncryptedPasswords;
        }

        // 创建并插入 LivePreviewTable
        LivePreviewTable livePreviewTable = new LivePreviewTable();
        livePreviewTable.setUrlId(dto.getChannelId());
        livePreviewTable.setName(dto.getChannel());
        livePreviewTable.setUrl(combinedEncryptedUrls);
        livePreviewTable.setPassword(combinedEncryptedPasswords);
        livePreviewTable.setLiveStream(0);

        // 插入新数据
        livePreviewTableMapper.insertLivePreviewTable(livePreviewTable);
        Long livePreviewTableId = livePreviewTable.getId();

        // 绑定分类
        for (Long liveTypeId : typeIdsSet) {
            LivePreviewType livePreviewType = new LivePreviewType();
            livePreviewType.setLiveId(livePreviewTableId);
            livePreviewType.setLiveTypeId(String.valueOf(liveTypeId));
            livePreviewTypeMapper.insertLivePreviewType(livePreviewType);
        }
    }

}
